package com.nanbei.a04;


import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;


/**
 * @ClassDescription: AutowiredAnnotationBeanPostProcessor 运行分析
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/9/11 9:46
 */
public class BigInAutowired {
    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        beanFactory.registerSingleton("bean2",new Bean2()); // 该创建方式不会再走 创建过程，依赖注入，初始化 这三个过程
        beanFactory.registerSingleton("bean3",new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //@Value
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${ } 的解析器

        // 1. 查找哪些属性、方法加了 @Autowired，这称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);
        Bean1 bean1 = new Bean1();
        System.out.println(bean1);
     //   processor.postProcessProperties(null,bean1,"bean1"); // 执行依赖注入 @Autowired  @Value
       // System.out.println(bean1);

        // processor.postProcessProperties(null,bean1,"bean1") 内部的 inject() 方法做了如下事情
        // 在最后获取到值以后通过反射将值赋值到bean中
        Method setHome = Bean1.class.getMethod("setHome", String.class);
        DependencyDescriptor dd0 = new DependencyDescriptor(new MethodParameter(setHome, 0), false);
        Object o = beanFactory.doResolveDependency(dd0, null, null, null);
        System.out.println(o);
       // setHome.invoke(bean1,o);

        Method setBean2 = Bean1.class.getMethod("setBean2", Bean2.class);
        DependencyDescriptor dd1 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
        Object o1 = beanFactory.doResolveDependency(dd1, null, null, null);
       // bean1.setBean2((Bean2)o1);
        System.out.println(o1);

        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd2 = new DependencyDescriptor(bean3, false);
        Object o2 = beanFactory.doResolveDependency(dd2, null, null, null);
        System.out.println(o2);
//        bean3.setAccessible(true);
//        bean3.set(bean1,o2);
//        System.out.println(bean1);
    }
}
